package com.jungle.sp.daily.controller.distrubuteLock;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.lock.LockService;
import com.alibaba.nacos.api.lock.NacosLockFactory;
import com.alibaba.nacos.client.lock.core.NLock;
import com.alibaba.nacos.client.lock.core.NLockFactory;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.baomidou.lock.annotation.Lock4j;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
 * @author Jungle
 * @create 2025-05-24 8:15
 * @description nacos分布式锁
 */
@Slf4j
@RestController
@RequestMapping("/nacosLock")
public class NacosLockController {

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 定义loc4jKey
     */
    private static final String LOCK4J_KEY = "lock4jKey";


    private static final Properties PROPERTIES = new Properties();

    static {
        PROPERTIES.setProperty(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
        PROPERTIES.setProperty(PropertyKeyConst.USERNAME, "nacos");
        PROPERTIES.setProperty(PropertyKeyConst.PASSWORD, "nacos");
    }


    /**
     * 这个锁锁不住，后续使用需要先验证
     */
    @GetMapping("/nacos")
    public String nacos() throws NacosException {

        LockService lockService = NacosLockFactory.createLockService(PROPERTIES);
        // 创建一个不带过期时间的锁
        NLock lockInstance = NLockFactory.getLock("testLockKey");

        Boolean acquired;
        try {
            acquired = lockService.lock(lockInstance);
            if (acquired) {
                // 成功获取锁，执行临界区操作
                log.info("成功获取锁: {}", lockInstance.getKey());
                // ... 执行您的业务逻辑 ... , mock 5秒钟
                ThreadUtils.sleep(5000);
                return "success";
            } else {
                // 未能获取锁
                log.error("未能获取锁: {}", lockInstance.getKey());
                return "fail";
            }
        } finally {
            lockService.unLock(lockInstance);
        }
    }


    @GetMapping("/redisson")
    public String testRedisson() throws InterruptedException {
        String lockKey = "redissonLockKey";
        RLock lock = redissonClient.getLock(lockKey);
        boolean acquired;
        try {
            acquired = lock.tryLock(1, TimeUnit.SECONDS);
            if (acquired) {
                // 成功获取锁，执行临界区操作
                log.info("成功获取锁: {}", lock.getName());
                // ... 执行您的业务逻辑 ... , mock 5秒钟
                ThreadUtils.sleep(5000);
                return "success";
            } else {
                // 未能获取锁
                log.error("未能获取锁: {}", lock.getName());
                return "fail";
            }
        } finally {
            lock.unlock();
        }
    }


    @GetMapping("/lock4j")
    @Lock4j
    @SneakyThrows
    public void testLock4j() {
        // TimeUnit.SECONDS.sleep(5);
        ThreadUtils.sleep(5000);
        log.info("Lock4j 分布式锁");

    }
}
